#region File Description
//  DomoBCI 
//  License: GNU/GPL
//  Developer: Federico Leonardo Motta
//  File description: This component lets the users login.
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Storage;
using DomoBCI.Core.GameManager;
using DomoBCI.gui;
using SharedContent;
#endregion

namespace DomoBCI.Core.Screens
{
    public delegate void LoginAction();
    public class Login : Microsoft.Xna.Framework.DrawableGameComponent
    {
        // Gli eventi dello Screen corrente.
        public event LoginAction OnLogin;
        public event LoginAction OnQuit;
        IComunicationManager cm;
        SpriteBatch spriteBatch;
        Texture2D tex;
        Vector2 pos_tex = Vector2.Zero;
        UIwin win;
        UIcontainer MainCont;
        UIbutton login,nuovo,del,quit;
        float screenscale;
        IInputManager InputManagerService;
        Rectangle area;
        IAsyncResult res;
        StorageDevice device;
        bool focus = true;
        int UserId=0;

        public Login(Game game)
            : base(game)
        {
            InputManagerService = (IInputManager)Game.Services.GetService(typeof(IInputManager));
            InputManagerService.EnterPressed += new PressedEventHandler(EnterIsPressed);
            InputManagerService.EnterReleased += new PressedEventHandler(EnterIsReleased);
            InputManagerService.TabPressed += new PressedEventHandler(TabIsPressed);
            InputManagerService.RightPressed += new PressedEventHandler(RightIsPressed);
            InputManagerService.LeftPressed += new PressedEventHandler(LeftIsPressed);
            InputManagerService.UpPressed += new PressedEventHandler(UpIsPressed);
            InputManagerService.DownPressed += new PressedEventHandler(DownIsPressed);
            cm = (IComunicationManager)Game.Services.GetService(typeof(IComunicationManager));
        }

        public override void Initialize()
        {
            res = StorageDevice.BeginShowSelector(0, null, null);
            device = StorageDevice.EndShowSelector(res);
            // Setto un fattore di scala
            screenscale = (float)Game.GraphicsDevice.Viewport.Width / 1600f;
            //carico lo sprite dai servizi
            spriteBatch = (Game.Services.GetService(typeof(SharedContext)) as SharedContext).sprite_batch;
            // Setto la Safe Area per i giochi che andranno su televisione
            area = Game.GraphicsDevice.Viewport.TitleSafeArea;

            // Instanzio la finestra principale
            tex = Game.Content.Load<Texture2D>(@"background1600");
            win = new UIwin(Game,"MainWin", new Vector2(0, 0), tex);

            // Calcolo due valori relativi in modo da poter renderizzare in maniera uguale su ogni risoluzione
            float x_pos = (float)Game.GraphicsDevice.Viewport.Width / 2.82f;
            float y_pos = (float)Game.GraphicsDevice.Viewport.Height / 3;

            // Creo il contenitore centrale e lo seleziono di default
            MainCont = new UIcontainer("MainCont", new Vector2(x_pos, y_pos), "maincont","maincont_sel",8, Game);
            MainCont.Select = true;

            // Creo i pulsanti del Menu, oguno con un nome, una posizione e le immagini correlate alle varie azioni:
            // (normale | selezionato | premuto | inattivo)
            login = new UIbutton("Login", new Vector2(x_pos + (x_pos * 0.05f), y_pos + (y_pos * 1.3f)), "GUI/login/login", "GUI/login/login_pres", "GUI/login/login_sel", "GUI/login/login_inact", Game);
            nuovo = new UIbutton("New", new Vector2(x_pos + (x_pos * 0.05f), y_pos + (y_pos * 1.12f)),
                                 "GUI/new/new", "GUI/new/new_pres",
                                 "GUI/new/new_sel", "GUI/new/new_inact", Game);
            del = new UIbutton("Delete", new Vector2(x_pos + (x_pos*0.45f), y_pos + (y_pos * 1.12f)),
                     "GUI/delete/delete", "GUI/delete/delete_pres",
                     "GUI/delete/delete_sel", "GUI/delete/delete_inact", Game);
            quit = new UIbutton("Quit", new Vector2(x_pos + (x_pos * 0.45f), y_pos + (y_pos * 1.3f)),
                     "GUI/quit/quit", "GUI/quit/quit_pres",
                     "GUI/quit/quit_sel", "GUI/quit/quit_inact", Game);
            UpdateUserList();

            base.Initialize();
        }


        public override void Update(GameTime gameTime)
        {
            // Aggiorno lo stato dei bottoni della Schermata corrente.
            MainCont.UpdateContainer(gameTime);
            nuovo.UpdateButton(gameTime);
            del.UpdateButton(gameTime);
            login.UpdateButton(gameTime);
            quit.UpdateButton(gameTime);
            base.Update(gameTime);
        }

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(Login));
            base.Dispose(disposing);
        }

        public void Detach()
        {
            // Detach the event and delete the list.
            InputManagerService.EnterPressed -= new PressedEventHandler(EnterIsPressed);
            InputManagerService.EnterReleased -= new PressedEventHandler(EnterIsReleased);
            InputManagerService.TabPressed -= new PressedEventHandler(TabIsPressed);
            InputManagerService.UpPressed -= new PressedEventHandler(UpIsPressed);
            InputManagerService.DownPressed -= new PressedEventHandler(DownIsPressed);
            InputManagerService = null;
        }

        public override void Draw(GameTime gameTime)
        {

            spriteBatch.Begin();
            // Disegno la finestra e il contenitore centrale.
            spriteBatch.Draw(win.Skin, win.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);
            spriteBatch.Draw(MainCont.CurrentSkin, MainCont.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);
            // Disegno i bottoni.
            spriteBatch.Draw(login.CurrentSkin, login.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);
            spriteBatch.Draw(nuovo.CurrentSkin, nuovo.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);
            spriteBatch.Draw(del.CurrentSkin, del.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);
            spriteBatch.Draw(quit.CurrentSkin, quit.Position, null, Color.White, 0f, Vector2.Zero, screenscale, SpriteEffects.None, 0f);

            // Disegno i labels corrispondenti agli utenti.
            if ((MainCont.CurrentPage != MainCont.Page) && (MainCont.Index > (MainCont.CurrentPage + 1) * MainCont.ElementsNumber - 1))
            {
                MainCont.CurrentPage++;
            }
            if ((MainCont.CurrentPage != 0) && (MainCont.Index <= (MainCont.CurrentPage) * MainCont.ElementsNumber - 1)) { MainCont.CurrentPage--; }

            int min = (int)MainCont.getPageElements().X;
            int max = (int)MainCont.getPageElements().Y;
            int scale = 0;
            for (int x = min; x < max; x++)
            {

                if (x == MainCont.Index)
                {
                    // Scritta gialla se selezionato.
                    spriteBatch.DrawString(MainCont.Labels.ElementAt(x).Font, MainCont.Labels.ElementAt(x).Text, new Vector2(MainCont.Position.X + (screenscale * 15), MainCont.Position.Y + (scale * screenscale * 50)), Color.Yellow, 0.0f, new Vector2(0, 0), screenscale * 1.2f, SpriteEffects.None, 0);
                    UserId = MainCont.Labels.ElementAt(x).ID;
                }
                else
                {
                    // Scritta bianca se non selezionato.
                    spriteBatch.DrawString(MainCont.Labels.ElementAt(x).Font, MainCont.Labels.ElementAt(x).Text, new Vector2(MainCont.Position.X + (screenscale * 15), MainCont.Position.Y + (scale * screenscale * 50)), Color.White, 0.0f, new Vector2(0, 0), screenscale * 1.2f, SpriteEffects.None, 0);
                }
                scale++;
            }


            spriteBatch.End();

            base.Draw(gameTime);
        }

        private void TabIsPressed()
        {
            if (focus)
            {
                if (MainCont.Select)
                {
                    MainCont.Select = false;
                    nuovo.Select = true;
                }
                else if (nuovo.Select)
                {
                    nuovo.Select = false;
                    del.Select = true;
                }
                else if (del.Select)
                {
                    del.Select = false;
                    if (login.IsActive)
                    {
                        login.Select = true;
                    }
                    else {
                        quit.Select = true;
                    }
                }
                else if (login.Select)
                {
                    login.Select = false;
                    quit.Select = true;
                }else if (quit.Select)
                {
                    quit.Select = false;
                    MainCont.Select = true;
                }
            }
        }

        private void EnterIsReleased(){
            if (focus)
            {
                if (MainCont.Select && login.IsActive)
                {
                    
                    cm.HIMLogin(UserId);
                    Game.setUser(getUser(UserId));
                    if (OnLogin != null) OnLogin();
                }
                if (nuovo.Select && nuovo.IsPressed)
                {
                    nuovo.IsPressed = false;
                    focus = false;
                    var UserDialog = new CreateUser(Game, InputManagerService, screenscale, area, spriteBatch);
                    UserDialog.OnCancel += () => focus = true;
                    UserDialog.OnCancel += () => Game.ComponentDispose(UserDialog);
                    UserDialog.OnConfirm += () => focus = true;
                    UserDialog.OnConfirm += () => Game.ComponentDispose(UserDialog);
                    UserDialog.OnConfirm += () => UpdateUserList();
                    Game.Components.Add(UserDialog);
                    
                }
                else if (del.Select && del.IsPressed)
                {
                    del.IsPressed = false;
                    FileManager fm = new FileManager();
                    fm.DoDelete(device,getUser(UserId));
                    
                    cm.HIMDeleteUser(UserId);
                    UpdateUserList();
                }
                else if (login.Select && login.IsPressed)
                {
                    login.IsPressed = false;
                    
                    cm.HIMLogin(UserId);
                    Game.setUser(getUser(UserId));
                    if (OnLogin != null) OnLogin();
                }
                else if (quit.Select && quit.IsPressed)
                {
                    quit.IsPressed = false;
                    if (OnQuit != null) { OnQuit(); }
                }
            }
        }

        private void EnterIsPressed(){
            if (focus)
            {
                if (nuovo.Select)
                {
                    nuovo.IsPressed = true;
                }
                else if (del.Select)
                {
                    del.IsPressed = true;
                }
                else if (login.Select)
                {
                    login.IsPressed = true;
                }
                else if (quit.Select)
                {
                    quit.IsPressed = true;

                }
            }
        }

        private void RightIsPressed() {
            if (focus) {
                if (focus)
                {
                    if (MainCont.Select)
                    {
                        MainCont.Select = false;
                        nuovo.Select = true;
                    }
                    else if (nuovo.Select)
                    {
                        nuovo.Select = false;
                        del.Select = true;
                    }
                    else if (del.Select)
                    {
                        del.Select = false;
                        if (login.IsActive)
                        {
                            login.Select = true;
                        }
                        else
                        {
                            quit.Select = true;
                        }
                    }
                    else if (login.Select)
                    {
                        login.Select = false;
                        quit.Select = true;
                    }
                    else if (quit.Select)
                    {
                        quit.Select = false;
                        MainCont.Select = true;
                    }
                }
            }
        }

        private void LeftIsPressed() {
            if (focus) {
                // TODO: Aggiungere lo spostamento orizzontale sx
            }
        }

        private void UpIsPressed()
        {
            if (focus)
            {
                if (MainCont.Select)
                {
                    if (MainCont.Index > 0) { MainCont.Index--; }
                }
            }
        }

        private void DownIsPressed()
        {
            if (focus)
            {
                if (MainCont.Select)
                {
                    if (MainCont.Index < MainCont.Labels.Count - 1) { MainCont.Index++; }
                }
            }
        }


        private void UpdateUserList() {
            FileManager fm = new FileManager();
            List<User> utenti = fm.GetUser(device);
            MainCont.Labels.RemoveRange(0, MainCont.Labels.Count);
            if (utenti.Count > 0)
            {
                foreach (User user in utenti)
                {
                    MainCont.AddLabel(new UIlabel(user.Id, user.Nome, user.Nome, "Arial", Game), MainCont.Position);
                }
                login.IsActive = true;
            }
            else {
                login.IsActive = false;
            }
        }

        private User getUser(int id) {
            FileManager fm = new FileManager();
            List<User> utenti = fm.GetUser(device);
            User usr = new User();
            foreach (User user in utenti)
            {
                if (user.Id == id) {
                    usr = user;
                    return usr;
                }
            }
            // TODO: Aggiungere un exception handler
            return usr;
        }
    }
}
